<script setup lang="ts">
import Sortable from "sortablejs";
import Add from "@iconify-icons/ep/plus";
import Eye from "@iconify-icons/ri/eye-line";
import Delete from "@iconify-icons/ri/delete-bin-7-line";
import type { UploadFile } from "element-plus";
import draggable from "vuedraggable/src/vuedraggable";
import { getKeyList, extractFields, downloadByData } from "@pureadmin/utils";
import { message } from "@/utils/message";
import { getToken, formatToken, getVisitorId } from "@/utils/auth";
import { UploadFileResult, FileType } from "@/store/utils";

defineOptions({
  name: "ReFileUpload"
});
const props = defineProps({
  modelValue: Array,
  /** 文件上传的接口地址 */
  uploadUrl: {
    type: String,
    default: import.meta.env.VITE_UPLOAD_URL
  },
  /** 列表类型  "picture-card" | "picture" | "text" */
  listType: {
    type: String as () => "picture-card" | "picture" | "text",
    default: "picture-card"
  },
  /** 数量限制 默认：1 */
  limit: {
    type: Number,
    default: 1
  },
  /** 上传文件类型 默认：所有
   * 图片: image/jpeg,image/png,image/gif,image/bmp,image/webp,image/svg+xml,image/x-icon
   * 所有图片: image/*
   * 视频: video/mp4,video/webm,video/ogg
   */
  accept: {
    type: String,
    default: "*"
  },
  /** 上传文件大小限制  默认 1 MB */
  size: {
    type: Number,
    default: 1
  },
  /** 提示 默认：显示 */
  tip: {
    type: Boolean,
    default: true
  },
  /** 图片比例 100*100 */
  scale: {
    type: String,
    default: ""
  },
  /** 显示上传列表 默认：true */
  showList: {
    type: Boolean,
    default: true
  },
  /** 校验方法，一版校验文件类型 */
  onValidate: {
    type: Function,
    default: () => {
      return { type: true, msg: "验证通过" };
    }
  },
  /** 成功 回调 */
  success: {
    type: Function,
    default: (data: FileType) => {}
  }
});
watch(
  () => props.modelValue,
  value => {
    console.log("value=====", value);
    fileList.value = value;
  },
  { deep: true }
);
const emit = defineEmits(["update:modelValue"]);
const fileList = ref([]);
const urlList = computed(() => getKeyList(fileList.value, "url"));
const curOpenImgIndex = ref(0);
const dialogVisible = ref(false);
const headers = reactive({
  Authorization: headerToken()
});
/** 上传文件前校验 */
const onBefore = file => {
  // 调用父组件的校验方法;
  const { type, msg } = props.onValidate(file);
  if (!type) {
    message(msg, { type: "warning" });
    return false;
  }
  const isExceed = file.size / 1024 / 1024 > props.size;
  if (isExceed) {
    message(`单个大小不能超过 ${props.size} MB!`, { type: "warning" });
    return false;
  }
};
/** 超出最大上传数时触发 */
const onExceed = () => {
  message(`最多上传 ${props.limit} 个，请先删除在上传`, {
    type: "warning"
  });
};
/** 移除上传的文件 */
const handleRemove = (file: UploadFile, list: UploadFile[]) => {
  fileList.value = list;
};
function handleSuccess(res: UploadFileResult, file: UploadFile) {
  fileList.value.push({
    ...file,
    path: res.data.path
  });
  emit("update:modelValue", fileList.value);
  props.success(res.data);
}
/** 上传失败 */
function handleError(err: any) {
  try {
    err = JSON.parse(err.message);
    message(err.message || "上传失败", { type: "error" });
  } catch (error) {
    message("上传失败", { type: "error" });
  }
}
/** 大图预览 */
const handlePictureCardPreview = (file: UploadFile) => {
  console.log("file=====", file);
  console.log("fileList=====", fileList);
  console.log(
    "fileList.value.findIndex(img => img.uid === file.uid)=====",
    fileList.value.findIndex(img => img.uid === file.uid)
  );
  curOpenImgIndex.value = fileList.value.findIndex(img => img.uid === file.uid);
  dialogVisible.value = true;
};
/** Token */
function headerToken(): string {
  const data = getToken();
  return formatToken(data.accessToken);
}
/** 指纹ID */
async function headerVisitorId() {
  headers["Visitor-id"] = await getVisitorId();
}
headerVisitorId();
</script>

<template>
  <el-upload
    drag
    :action="uploadUrl"
    :multiple="limit > 1"
    :file-list="fileList"
    :limit="limit"
    :accept="accept"
    :list-type="listType"
    :show-file-list="showList"
    :headers="headers"
    :before-upload="onBefore"
    :on-exceed="onExceed"
    :on-remove="handleRemove"
    :on-success="handleSuccess"
    :on-error="handleError"
    :on-preview="handlePictureCardPreview"
  >
    <template v-if="tip" #tip>
      <div>
        <div class="el-upload__tip">
          <span v-if="scale" class="mr-3"
            >推荐大小<b class="m-1" style="color: var(--el-color-primary)">{{
              scale
            }}</b></span
          >
          <span v-if="size" class="mr-3"
            >大小不超过<b class="m-1" style="color: var(--el-color-primary)">{{
              size
            }}</b
            >MB</span
          >
          <span v-if="limit > 1" class="mr-3"
            >最大上传<b class="m-1" style="color: var(--el-color-primary)">{{
              limit
            }}</b
            >个</span
          >
          <span v-if="accept !== '*'"
            >格式为<span class="m-1" style="color: var(--el-color-primary)">{{
              accept
            }}</span
            >的文件</span
          >
        </div>
      </div>
    </template>
    <template #default>
      <slot>
        <div class="flex justify-center h-full items-center">
          <IconifyIconOffline :icon="Add" class="" width="30" />
        </div>
      </slot>
    </template>
    <template #file="{ file }">
      <div
        v-if="['uploading', 'ready'].includes(file.status)"
        class="mt-[35%] m-auto"
      >
        <p class="font-medium">正在上传</p>
        <el-progress
          class="mt-2"
          :text-inside="true"
          :stroke-width="16"
          :percentage="file.percentage"
        />
      </div>
    </template>
  </el-upload>
  <el-image-viewer
    v-if="dialogVisible"
    :initialIndex="curOpenImgIndex"
    :url-list="urlList"
    :zoom-rate="1.2"
    :max-scale="7"
    :min-scale="0.2"
    @close="dialogVisible = false"
    @switch="index => (curOpenImgIndex = index)"
  />
</template>

<style lang="scss" scoped>
:deep(.el-upload-dragger) {
  padding: 0;
  width: 100%;
  height: 100%;
  background-color: transparent;
  border: none;
}
</style>
